//
//  YCScanViewController.m
//  YCCodeScan
//
//  Created by 唐可雄 on 16/9/29.
//  Copyright © 2016年 swustyc. All rights reserved.
//

#import "YCScanViewController.h"

#import <AVFoundation/AVFoundation.h>

#define kTimer_TimeInterval 0.05f
#define kLine_Height_MAX 200.f
#define kLine_Height_Min 0.f
#define kLine_Factor_Increase 5.f

@interface YCScanViewController ()<AVCaptureMetadataOutputObjectsDelegate>

/** 摄像机会话对象 */
@property (strong, nonatomic) AVCaptureSession *session;
/** 摄像机预览图层 */
@property (strong, nonatomic) AVCaptureVideoPreviewLayer *previewLayer;
/** 设备 */
@property (strong, nonatomic) AVCaptureDevice *device;
/** 定时器，刷新屏幕 */
@property (strong, nonatomic) NSTimer *timer;

@end

@implementation YCScanViewController

#pragma mark - Override Methods

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    // 安装扫描引擎
    [self installScanEngine];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    
    self.timer =[NSTimer scheduledTimerWithTimeInterval:kTimer_TimeInterval target:self selector:@selector(animation_line_action) userInfo:nil repeats:YES];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    
    // 卸载扫描引擎
    [self uninstallScanEngine];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    
    [self.timer invalidate];
    self.timer = nil;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

#pragma mark - Private Methods

/**
 安装扫描引擎
 */
- (void)installScanEngine {
    // 1、 获取摄像设备
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    // 2、 创建输入流
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
    // 3、 创建输出流
    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
    // 4、设置代理 在主线程里刷新
    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    // 设置扫描范围(每一个取值0～1，以屏幕左上角为坐标原点)
    CGFloat widthScreen = [UIScreen mainScreen].bounds.size.width;
    CGFloat heightScreen = [UIScreen mainScreen].bounds.size.height;
    double scaleX = (widthScreen-200.)/2/widthScreen;
    double scaleY = (heightScreen-200.)/2/heightScreen;
    double scaleWith = 200./widthScreen;
    double scaleHeight = 200./heightScreen;
        // 特别注意：这里要反过来
    output.rectOfInterest = CGRectMake(scaleY, scaleX, scaleHeight, scaleWith);
    // 5、 初始化链接对象（会话对象）
    self.session = [[AVCaptureSession alloc] init];
        // 高质量采集率
    [self.session setSessionPreset:AVCaptureSessionPresetHigh];
        // 5.1 添加会话输入
    [self.session addInput:input];
        // 5.2 添加会话输出
    [self.session addOutput:output];
    // 6、设置输出数据类型，需要将元数据输出添加到会话后，才能指定元数据类型，否则会报错
        // 设置扫码支持的编码格式(如下设置条形码和二维码兼容)
    output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code,  AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
    // 7、实例化预览图层, 传递self.session是为了告诉图层将来显示什么内容
    self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
    self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    self.previewLayer.frame = self.view.layer.bounds;
    // 8、将图层插入当前视图
    [self.view.layer insertSublayer:self.previewLayer atIndex:0];
    // 9、启动会话
    [self.session startRunning];
}

/**
 卸载扫描引擎
 */
- (void)uninstallScanEngine {
    // 1、移除图层
    [self.previewLayer removeFromSuperlayer];
    // 2、关闭会话
    [self.session stopRunning];
}

/**
 配置手电筒

 @param state 状态
 */
- (void)configTorch:(BOOL)state {
    self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    if ([self.device hasTorch]) {
        [self.device lockForConfiguration:nil];
        if (state) {
            [self.device setTorchMode:AVCaptureTorchModeOn];
        } else {
            [self.device setTorchMode: AVCaptureTorchModeOff];
        }
        [self.device unlockForConfiguration];
    }
}

#pragma mark - NSTimer

/**
 扫描线条动画
 */
- (void)animation_line_action {
    CGFloat height = self.constraintLineImgViewHeight.constant;
    
    height += kLine_Factor_Increase;
    
    if (height > kLine_Height_MAX) {
        height = kLine_Height_Min;
    }
    
    self.constraintLineImgViewHeight.constant = height;
    
    [self.lineImgView layoutIfNeeded];
}

#pragma mark - IBAction

/**
 点击返回按钮

 @param sender 返回按钮
 */
- (IBAction)backBtnDidClick:(id)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

/**
 点击闪光灯按钮

 @param sender 闪光灯按钮
 */
- (IBAction)flashBtnDidClick:(id)sender {
    self.flashBtn.selected = !self.flashBtn.selected;
    
    [self configTorch:self.flashBtn.selected];
}

#pragma mark - AVCaptureMetadataOutputObjectsDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
    // 扫描结果处理
    if (metadataObjects.count > 0) {
        AVMetadataMachineReadableCodeObject *obj = metadataObjects[0];
        NSString *result = obj.stringValue;
        
        NSLog(@"%@", result);
    }
}

@end
